/*---------------------------------------------------------------------
 * File name: hal_uart.h
 *
 * Copyright (c) <2020-2022>, <ChenLong>
 *
 * All rights reserved.
 *
 * Author: ChenLong
 * Email: worldlong@foxmail.com
 *--------------------------------------------------------------------*/
#pragma once
/*
*/
#include "hal_gpio.h"
/*
*/
#define HUART_PORT_BITS    4
#define HUART_DATA_BITS    2
#define HUART_PARITY_BITS  2
#define HUART_STOP_BITS    2
#define HUART_BAUD_BITS    20

#define HUART_PORT_POS    (0)
#define HUART_DATA_POS    (HUART_PORT_POS + HUART_PORT_BITS)
#define HUART_PARITY_POS  (HUART_DATA_POS + HUART_DATA_BITS)
#define HUART_STOP_POS    (HUART_PARITY_POS + HUART_PARITY_BITS)
#define HUART_BAUD_POS    (HUART_STOP_POS + HUART_STOP_BITS)

#define HUART_PORT_MASK    ((1<<HUART_PORT_BITS) - 1)
#define HUART_DATA_MASK    ((1<<HUART_DATA_BITS) - 1)
#define HUART_PARITY_MASK  ((1<<HUART_PARITY_BITS) - 1)
#define HUART_STOP_MASK    ((1<<HUART_STOP_BITS) - 1)
#define HUART_BAUD_MASK    ((1<<HUART_BAUD_BITS) - 1)
#define HUART_CFG_MASK     ((HUART_DATA_MASK << HUART_DATA_POS)     |\
                            (HUART_PARITY_MASK << HUART_PARITY_POS) |\
                            (HUART_STOP_MASK << HUART_STOP_POS)     |\
                            (HUART_BAUD_MASK << HUART_BAUD_POS))
/*
*/
#define HUART_0            (1 << HUART_PORT_POS)
#define HUART_1            (2 << HUART_PORT_POS)
#define HUART_2            (3 << HUART_PORT_POS)
#define HUART_3            (4 << HUART_PORT_POS)
#define HUART_4            (5 << HUART_PORT_POS)
#define HUART_5            (6 << HUART_PORT_POS)
#define HUART_6            (7 << HUART_PORT_POS)
#define HUART_7            (8 << HUART_PORT_POS)
#define HUART_8            (9 << HUART_PORT_POS)
#define HUART_PORT(param)  (HUART_##param >> HUART_PORT_POS)
/*
*/
#define HUART_DATA_8B      (0 << HUART_DATA_POS)
#define HUART_DATA_9B      (1 << HUART_DATA_POS)
#define HUART_DATA(param)  (HUART_DATA_##param >> HUART_DATA_POS)
/*
*/
#define HUART_PARITY_NONE    (0 << HUART_PARITY_POS)
#define HUART_PARITY_EVEN    (1 << HUART_PARITY_POS)
#define HUART_PARITY_ODD     (2 << HUART_PARITY_POS)
#define HUART_PARITY(param)  (HUART_PARITY_##param >> HUART_PARITY_POS)
/*
*/
#define HUART_STOP_0B5     (0 << HUART_STOP_POS)
#define HUART_STOP_1B      (1 << HUART_STOP_POS)
#define HUART_STOP_1B5     (2 << HUART_STOP_POS)
#define HUART_STOP_2B      (3 << HUART_STOP_POS)
#define HUART_STOP(param)  (HUART_STOP_##param >> HUART_STOP_POS)
/*
*/
#define HUART_BAUD(baud)  (baud << HUART_BAUD_POS)
/*
*/
#define HUART_CFG_EXTRACT(cfg, name)  ((cfg >> HUART_##name##_POS) & HUART_##name##_MASK)
/*
*/
class HAL_UART
{
public:
  HAL_UART():
    port(0),
    cfg(0),
    rx_pin(nullptr),
    tx_pin(nullptr)
  {}
  
  uint32_t port;
  uint32_t cfg;
  HAL_GPIO *rx_pin;
  HAL_GPIO *tx_pin;
  
  bool init(uint32_t cfg0);
  bool config(uint32_t cfg0);  //Just config the param with CFG_MASK
  int  read(uint8_t *buffer, uint32_t num);
  int  write(uint8_t *buffer, uint32_t num);
  int  write(uint8_t *buffer, uint32_t num, uint32_t ms); 
  int  write_block(uint8_t *buffer, uint32_t num);
  int rx_buffer_number();
  int tx_buffer_number();
  void flush();
  void attach_pin(HAL_GPIO *rx_pin0, HAL_GPIO *tx_pin0) {
    rx_pin = rx_pin0;
    tx_pin = tx_pin0;
  }
  void detach_pin() {
    attach_pin(nullptr, nullptr);
  }
  void attach_rx_irq(void(*fun)(void *param, uint32_t flag), void *param);
  void attach_tx_irq(void(*fun)(void *param, uint32_t flag), void *param);
  void detach_rx_irq() {
    attach_rx_irq(nullptr, nullptr);
  }
  void detach_tx_irq() {
    attach_tx_irq(nullptr, nullptr);
  }
private:
  int _index;
};






